package team.nine.kuaichezuche.service.impl;

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import team.nine.kuaichezuche.model.User;
import team.nine.kuaichezuche.repository.UserRepository;
import team.nine.kuaichezuche.service.RedisService;
import team.nine.kuaichezuche.service.UserService;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 用户服务实现类，实现用户相关的业务逻辑
 */
@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private RedisService redisService;
    
    // 用于密码加密的编码器
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    
    // Redis存储验证码的键前缀
    private static final String VERIFICATION_CODE_PREFIX = "verification:code:";
    
    /**
     * 用户注册业务逻辑
     */
    @Override
    public User register(User user) throws Exception {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(user.getUsername())) {
            throw new Exception("用户名已存在");
        }
        
        // 检查手机号是否已存在
        if (userRepository.existsByPhone(user.getPhone())) {
            throw new Exception("手机号已被注册");
        }
        
        // 检查身份证号是否已存在
        if (userRepository.existsByIdCard(user.getIdCard())) {
            throw new Exception("身份证号已被注册");
        }
        
        // 密码加密
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        
        // 生成用户令牌
        String token = generateToken(null); // 先生成一个临时令牌
        user.setToken(token);
        
        // 设置创建时间（通过实体类中的@PrePersist注解自动设置）
        
        // 保存用户信息到数据库
        User savedUser = userRepository.save(user);
        
        // 重新生成包含用户ID的令牌
        String finalToken = generateToken(savedUser.getId());
        savedUser.setToken(finalToken);
        return userRepository.save(savedUser);
    }
    
    /**
     * 根据用户名获取用户信息
     */
    @Override
    public User getUserByUsername(String username) {
        return userRepository.findByUsername(username);
    }
    
    /**
     * 根据手机号获取用户信息
     */
    @Override
    public User getUserByPhone(String phone) {
        return userRepository.findByPhone(phone);
    }
    
    /**
     * 生成用户令牌
     */
    @Override
    public String generateToken(Long userId) {
        // 使用UUID和随机字符串生成令牌
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String randomString = RandomStringUtils.randomAlphanumeric(16);
        String timestamp = String.valueOf(new Date().getTime());
        
        StringBuilder tokenBuilder = new StringBuilder();
        tokenBuilder.append("token_");
        if (userId != null) {
            tokenBuilder.append("u").append(userId).append("_");
        }
        tokenBuilder.append(uuid).append("_");
        tokenBuilder.append(randomString).append("_");
        tokenBuilder.append(timestamp);
        
        return tokenBuilder.toString();
    }
    
    /**
     * 用户登录业务逻辑
     */
    @Override
    public User login(String phoneNumber, String password) throws Exception {
        // 根据手机号查找用户
        User user = userRepository.findByPhone(phoneNumber);
        
        // 检查用户是否存在
        if (user == null) {
            throw new Exception("USER_NOT_REGISTERED");
        }
        
        // 验证密码是否匹配
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new Exception("INVALID_PASSWORD");
        }
        
        // 生成新的令牌
        String newToken = generateToken(user.getId());
        user.setToken(newToken);
        
        // 更新用户令牌
        return userRepository.save(user);
    }
    
    @Override
    public User getUserByToken(String token) throws Exception {
        // 根据令牌查找用户
        User user = userRepository.findByToken(token);
        
        // 检查用户是否存在
        if (user == null) {
            throw new Exception("无效的令牌");
        }
        
        return user;
    }
    
    @Override
    public User changePassword(String phoneNumber, String verificationCode, String newPassword) throws Exception {
        // 构建Redis中验证码的键
        String redisKey = VERIFICATION_CODE_PREFIX + phoneNumber;
        
        // 检查Redis中是否存在该手机号的验证码
        if (!redisService.hasKey(redisKey)) {
            throw new Exception("4003"); // 验证码不存在或已过期
        }
        
        // 获取Redis中存储的验证码
        String storedCode = (String) redisService.get(redisKey);
        
        // 验证验证码是否正确
        if (storedCode == null || !storedCode.equals(verificationCode)) {
            throw new Exception("4003"); // 验证码不正确
        }
        
        // 在MySQL中搜索该手机号
        User user = userRepository.findByPhone(phoneNumber);
        
        // 检查用户是否存在
        if (user == null) {
            throw new Exception("4001"); // 用户未注册
        }
        
        // 加密新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        
        // 生成新的令牌
        String newToken = generateToken(user.getId());
        user.setToken(newToken);
        
        // 保存更新后的用户信息
        User updatedUser = userRepository.save(user);
        
        // 删除已使用的验证码
        redisService.delete(redisKey);
        
        return updatedUser;
    }
}